﻿#include "dxstdafx.h"
#include "GuiConfigIO.h"
#include "DialogManager.h"
#include "GuiCommonConfig.h"
#include "Data/DataMgr.h"
#include "Data/ScriptData/Localisation/Localisation.h"

extern CGuiCommonConfig g_GuiCommonConfig;

#define GUI_NORMAL_PUSHBACK(P, T)\
[this](const void* vp){ CHECK_RETURN(vp);\
		_stGuiProperty* cp = static_cast<_stGuiProperty*>(m_list_OperatorPtr.back());\
		CHECK_RETURN(cp);\
		const T* tp = static_cast<const T*>(vp);\
		CHECK_RETURN(tp);\
		cp->P.push_back(*tp); }\

// (_stGuiProperty*)(m_list_OperatorPtr.back())->P = (*T)(vp)  普通赋值操作
#define GUI_NORMAL_ASSIGN(P, T)\
[this](const void* vp){ CHECK_RETURN(vp);\
		_stGuiProperty* cp = static_cast<_stGuiProperty*>(m_list_OperatorPtr.back());\
		CHECK_RETURN(cp);\
		const T* tp = static_cast<const T*>(vp);\
		CHECK_RETURN(tp);\
		cp->P = *tp; }\

#define GUI_DIALOGNAME_NORMAL_ASSIGN(P)\
[this](const void* vp){ CHECK_RETURN(vp);\
		if (m_list_StartObjKey.empty() || L"Dialog" != m_list_StartObjKey.back()) return;\
		_stGuiProperty* cp = static_cast<_stGuiProperty*>(m_list_OperatorPtr.back());\
		CHECK_RETURN(cp);\
		const std::wstring* tp = static_cast<const std::wstring*>(vp);\
		CHECK_RETURN(tp);\
		cp->P = *tp;\
		m_strDialogName = *tp;}\

GuiPropertyReaderHandle::GuiPropertyReaderHandle(void*)
	: BaseReaderHandler(nullptr)
{
	m_map_OperatorFunction = {
		{ L"enable", GUI_NORMAL_ASSIGN(bEnable, bool) },
		{ L"visible", GUI_NORMAL_ASSIGN(bVisible, bool) },
		{ L"id", GUI_NORMAL_ASSIGN(nID, int) },
		{ L"font", GUI_NORMAL_ASSIGN(nFontIndex, int) },
		{ L"textFormat", GUI_NORMAL_ASSIGN(nTextFormat, int) },
		{ L"width", GUI_NORMAL_ASSIGN(nWidth, int) },
		{ L"height", GUI_NORMAL_ASSIGN(nHeight, int) },
		{ L"offsetx", GUI_NORMAL_ASSIGN(nOffsetX, int) },
		{ L"offsety", GUI_NORMAL_ASSIGN(nOffsetY, int) },
		{ L"orientation", GUI_NORMAL_ASSIGN(strOrientation, std::wstring) },		// Dialog的实现了 控件的没实现
		{ L"4state", GUI_NORMAL_ASSIGN(n4State, int) },
		{ L"name", GUI_DIALOGNAME_NORMAL_ASSIGN(DialogName) },
		{ L"text_index", GUI_NORMAL_ASSIGN(strTextIndex, std::wstring) },
		{ L"texturefile", GUI_NORMAL_ASSIGN(srcPath, std::wstring) },
		{ L"textColor", GUI_NORMAL_PUSHBACK(vecTextColor, int) },
	};
}

bool GuiPropertyReaderHandle::HandleBool(const std::wstring& key, bool b)
{
	return OperatorFunction(key, &b);
}

bool GuiPropertyReaderHandle::HandleInt(const std::wstring& key, int i)
{
	return OperatorFunction(key, &i);
}

bool GuiPropertyReaderHandle::HandleString(const std::wstring& key, const std::wstring& str)
{
	return OperatorFunction(key, &str);
}

bool GuiPropertyReaderHandle::HandleStartObj(const std::wstring& key)
{
	if (L"Dialog" == key)
	{
		m_strDialogName.clear();
	}
	if (!m_list_StartObjKey.empty() && L"Dialog" == m_list_StartObjKey.back())
	{
		// 创建Dialog 但如果此dialog没有其他具体ui 则不会被创建
		if (FAILED(CreateGUI()))
		{
			assert(0);
			return false;
		}
		// 创建完需要删除 防止重复创建
		m_list_StartObjKey.pop_back();
		if (!m_list_OperatorPtr.empty())
		{
			m_list_OperatorPtr.pop_back();
		}
	}
	if (!key.empty())
	{
		m_stGuiProperty.clear();
		m_stGuiProperty.UIType = key;
		m_list_OperatorPtr.push_back(&m_stGuiProperty);
	}
	
	return BaseReaderHandler::HandleStartObj(key);
}

bool GuiPropertyReaderHandle::HandleEndObj()
{
	if (!m_list_StartObjKey.empty() && L"Dialog" != m_list_StartObjKey.back())
	{
		// 创建除Dialog之外的ui
		if (FAILED(CreateGUI()))
		{
			assert(0);
			return false;
		}
	}

	if (!m_list_OperatorPtr.empty())
	{
		m_list_OperatorPtr.pop_back();
	}
	return BaseReaderHandler::HandleEndObj();
}

HRESULT GuiPropertyReaderHandle::CreateGUI()
{
	HRESULT hr = S_OK;
	// 取CDXUTDialog
	CDXUTDialog* pDialog = DialogManager::Singleten().GetDialog(m_strDialogName);
	if (nullptr == pDialog)
	{
		return -1;
	}
	// 取数据
	_stGuiProperty* pGui = static_cast<_stGuiProperty*>(m_list_OperatorPtr.back());
	if (nullptr == pGui)
	{
		return -1;
	}
	if (L"Dialog" == pGui->UIType)
	{
		pDialog->SetSize(pGui->nWidth, pGui->nHeight);
		pDialog->SetLocation(pGui->nOffsetX, pGui->nOffsetY);
		pDialog->SetVisible(pGui->bVisible);
		{
			auto p_unique = std::make_unique<_stGuiProperty>(*pGui);
			pDialog->m_pProperty = std::move(p_unique);
		}
		g_GuiCommonConfig.SetDialogFont(pDialog);
	}
	else
	{
		pGui->DialogName = m_strDialogName;
		if (L"Static" == pGui->UIType)
		{
			CDXUTStatic* pStatic = new CDXUTStatic(pDialog);	// 调用了AddControl之后 就不用自己管理了
			{
				auto p_unique = std::make_unique<_stGuiProperty>(*pGui);
				pStatic->m_pProperty = std::move(p_unique);
			}
			
			{
				std::wstring strText;
				if (g_Localisation->GetLocalisation(pGui->strTextIndex, strText))
				{
					V_RETURN(pStatic->SetText(strText.c_str()));
				}
				else
				{
					V_RETURN(pStatic->SetText(L""));
				}
			}

			V_RETURN(pDialog->AddControl(pStatic));
			SetCommonProperty(pStatic);		// 最好在AddControl之后做

			if (!pGui->srcPath.empty())
			{
				std::wstring szFullPathOut;
				CommonFunc::RelativePath2FullPath(pGui->srcPath, szFullPathOut); // 纹理路径
				int TextureIndex = pDialog->GetTextureSize();
				V_RETURN(pDialog->SetTexture(TextureIndex, szFullPathOut.c_str(), pGui->nWidth, pGui->nHeight));
				CDXUTElement Element;
				RECT rcTexture;
				SetRect(&rcTexture, 0, 0, pGui->nWidth, pGui->nHeight);
				Element.SetTexture(TextureIndex, &rcTexture);
				Element.SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
				V_RETURN(pStatic->SetElement(0, &Element));
			}
			else
			{
				CDXUTElement* pElement = pStatic->GetElement(0);
				if (pElement)
				{
					pElement->SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
				}
			}
		}
		else if (L"Image" == pGui->UIType)
		{
			CDXUTImage* pImage = new CDXUTImage(pDialog);		// 调用了AddControl之后 就不用自己管理了
			{
				auto p_unique = std::make_unique<_stGuiProperty>(*pGui);
				pImage->m_pProperty = std::move(p_unique);
			}
			
			V_RETURN(pDialog->AddControl(pImage));
			SetCommonProperty(pImage);		// 最好在AddControl之后做

			if (!pGui->srcPath.empty())
			{
				std::wstring szFullPathOut;
				CommonFunc::RelativePath2FullPath(pGui->srcPath, szFullPathOut); // 纹理路径
				int TextureIndex = pDialog->GetTextureSize();
				V_RETURN(pDialog->SetTexture(TextureIndex, szFullPathOut.c_str(), pGui->nWidth, pGui->nHeight));
				CDXUTElement Element;
				RECT rcTexture;
				SetRect(&rcTexture, 0, 0, pGui->nWidth, pGui->nHeight);
				Element.SetTexture(TextureIndex, &rcTexture);
				V_RETURN(pImage->SetElement(0, &Element));
			}
		}
		else if (L"Button" == pGui->UIType)
		{
			CDXUTButton* pButton = new CDXUTButton(pDialog);		// 调用了AddControl之后 就不用自己管理了
			{
				auto p_unique = std::make_unique<_stGuiProperty>(*pGui);
				pButton->m_pProperty = std::move(p_unique);
			}
			
			pButton->Set4State(pGui->n4State);

			{
				std::wstring strText;
				if (g_Localisation->GetLocalisation(pGui->strTextIndex, strText))
				{
					V_RETURN(pButton->SetText(strText.c_str()));
				}
				else
				{
					V_RETURN(pButton->SetText(L""));
				}
			}

			V_RETURN(pDialog->AddControl(pButton));
			SetCommonProperty(pButton);		// 最好在AddControl之后做

			if (!pGui->srcPath.empty())
			{
				std::wstring szFullPathOut;
				CommonFunc::RelativePath2FullPath(pGui->srcPath, szFullPathOut); // 纹理路径
				int TextureIndex = pDialog->GetTextureSize();
				V_RETURN(pDialog->SetTexture(TextureIndex, szFullPathOut.c_str(), pGui->nWidth * pGui->n4State, pGui->nHeight));
				CDXUTElement Element;
				RECT rcTexture;
				for (int i = 0; i < pGui->n4State; ++i)
				{
					SetRect(&rcTexture, i * pGui->nWidth, 0, (i + 1) * pGui->nWidth, pGui->nHeight);
					Element.SetTexture(TextureIndex, &rcTexture);					
					Element.SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
					V_RETURN(pButton->SetElement(i, &Element));
				}
				if (1 == pGui->n4State)
				{
					SetRect(&rcTexture, 0, 0, pGui->nWidth, pGui->nHeight);
					Element.SetTexture(TextureIndex, &rcTexture);
					Element.SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
					V_RETURN(pButton->FillElement(&Element, &rcTexture, TextureIndex));
				}
			}
			else
			{
				for (int i = 0; i < 2; ++i)
				{
					CDXUTElement* pElement = pButton->GetElement(i);
					if (pElement)
					{
						pElement->SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
					}
				}
			}
		}
		else if (L"CheckBox" == pGui->UIType)
		{
			//
		}
		else if (L"RadioButton" == pGui->UIType)
		{
			//
		}
		else if (L"ListBox" == pGui->UIType)
		{
			//
		}
		else if (L"ComboBox" == pGui->UIType)
		{
			//
		}
		else if (L"Slider" == pGui->UIType)
		{
			//
		}
		else if (L"EditBox" == pGui->UIType)
		{
			CDXUTEditBox* pEditBox = new CDXUTEditBox(pDialog);		// 调用了AddControl之后 就不用自己管理了
			{
				auto p_unique = std::make_unique<_stGuiProperty>(*pGui);
				pEditBox->m_pProperty = std::move(p_unique);
			}
			
			{
				std::wstring strText;
				if (g_Localisation->GetLocalisation(pGui->strTextIndex, strText))
				{
					pEditBox->SetText(strText.c_str());
				}
				else
				{
					pEditBox->SetText(L"");
				}
			}

			V_RETURN(pDialog->AddControl(pEditBox));
			SetCommonProperty(pEditBox);		// 最好在AddControl之后做

			if (!pGui->srcPath.empty())
			{
				std::wstring szFullPathOut;
				CommonFunc::RelativePath2FullPath(pGui->srcPath, szFullPathOut); // 纹理路径
				int TextureIndex = pDialog->GetTextureSize();
				V_RETURN(pDialog->SetTexture(TextureIndex, szFullPathOut.c_str(), pGui->nWidth, pGui->nHeight));
				CDXUTElement Element;
				RECT rcTexture;
				SetRect(&rcTexture, 0, 0, pGui->nWidth, pGui->nHeight);
				Element.SetTexture(TextureIndex, &rcTexture);
				Element.SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
				V_RETURN(pEditBox->SetElement(0, &Element));
			}
			else
			{
				CDXUTElement* pElement = pEditBox->GetElement(0);
				if (pElement)
				{
					pElement->SetFont(pGui->nFontIndex, GetPropertyFontColor(pGui), pGui->nTextFormat);
				}
			}
		}
	}
	return hr;
}

void GuiPropertyReaderHandle::SetCommonProperty(CDXUTControl* pControl)
{
	CHECK_RETURN(pControl);
	CHECK_RETURN(pControl->m_pProperty);

	pControl->SetID(pControl->m_pProperty->nID);
	pControl->SetSize(pControl->m_pProperty->nWidth, pControl->m_pProperty->nHeight);
	pControl->SetLocation(pControl->m_pProperty->nOffsetX, pControl->m_pProperty->nOffsetY);
	pControl->SetEnabled(pControl->m_pProperty->bEnable);
	pControl->SetVisible(pControl->m_pProperty->bVisible);
}

D3DCOLOR GuiPropertyReaderHandle::GetPropertyFontColor(const _stGuiProperty* pProperty) const
{
	if (pProperty && 3 == pProperty->vecTextColor.size())
	{
		return D3DCOLOR_RGBA(pProperty->vecTextColor[0], pProperty->vecTextColor[1], pProperty->vecTextColor[2], 255);
	}
	return D3DCOLOR_ARGB(255, 255, 255, 255);
}

// (_FontStruct*)(m_list_OperatorPtr.back())->P = (*T)(vp)  普通赋值操作
#define FONT_NORMAL_ASSIGN(P, T)\
[this](const void* vp){ CHECK_RETURN(vp);\
		_FontStruct* cp = static_cast<_FontStruct*>(m_list_OperatorPtr.back());\
		CHECK_RETURN(cp);\
		const T* tp = static_cast<const T*>(vp);\
		CHECK_RETURN(tp);\
		cp->P =  *tp; }\

FontReaderHandle::FontReaderHandle(std::unordered_map<WORD, _FontStruct>* map)
	: BaseReaderHandler(map)
{
	m_map_OperatorFunction = {
		{ L"fontIndex", FONT_NORMAL_ASSIGN(fontId, int) },
		{ L"fontHeight", FONT_NORMAL_ASSIGN(fontHeight, int) },
		{ L"fontWeight", FONT_NORMAL_ASSIGN(fontWeight, int) },
	};
}

bool FontReaderHandle::HandleStartObj(const std::wstring& key)
{
	if (!key.empty())
	{
		m_FontStruct.clear();
		m_FontStruct.fontName = key;
		m_list_OperatorPtr.push_back(&m_FontStruct);
	}	
	return true;
}

bool FontReaderHandle::HandleInt(const std::wstring& key, int i)
{
	return OperatorFunction(key, &i);
}

bool FontReaderHandle::HandleEndObj()
{
	if (m_list_OperatorPtr.empty())
	{
		return true;
	}
	// 非空 需要操作 m_Container
	// 因为KEY要在HandleInt()中才能取到 所以不能在HandleStartObj()中就赋值
	_FontStruct* pFontStruct = static_cast<_FontStruct*>(m_list_OperatorPtr.back());
	CHECK_RE_FALSE(pFontStruct);
	CHECK_RE_FALSE(m_Container);
	auto iterInsert = m_Container->insert(std::make_pair(pFontStruct->fontId, *pFontStruct));
	if (!iterInsert.second)
	{
		CString strError;
		strError.Format(L"'%s' is repeat!", pFontStruct->fontId);
		CommonFunc::ErrorMessageBox(strError);
		return false;
	}
	else
	{
		// 成功 则pop_back m_list_OperatorPtr
		m_list_OperatorPtr.pop_back();
	}
	return true;
}



bool Dialog2GuiReaderHandle::HandleString(const std::wstring& key, const std::wstring& str)
{
	CHECK_RE_FALSE(m_Container);
	auto iterInsert = m_Container->insert(std::make_pair(key, str));
	if (!iterInsert.second)
	{
		// 插入失败 说明重复
		if (iterInsert.first->second.empty())
		{
			// 值是空 覆盖就好
			iterInsert.first->second = str;
		}
		else
		{
			CString strError;
			strError.Format(L"Key '%s' is repeat!", key);
			CommonFunc::ErrorMessageBox(strError);
			return false;
		}
	}	
	return true;
}
